//圆形Image扩展组件，支持圆形碰撞检测
using UnityEngine;
using UnityEngine.UI;

[AddComponentMenu("BToolkit/ImagePolygon")]
public class ImagePolygon : Image
{
    public float texScale = 1;
    public RectTransform[] points = new RectTransform[4];

    private Vector2[] poses = new Vector2[0];

    void Update()
    {
        if (poses.Length != points.Length) poses = new Vector2[points.Length];
        for (int i = 0; i < points.Length; i++)
        {
            RectTransform point = points[i];
            if (point && poses[i] != point.anchoredPosition)
            {
                poses[i] = point.anchoredPosition;
                this.SetAllDirty();
                RefreshSizeDelta();
            }
        }
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();

        //圆心
        Vector2 centerUV = Vector2.zero;
        AddVertex(vh, centerUV);
        //外圈
        bool isAllReady = true;
        for (int i = 0; i < points.Length; i++)
        {
            if (!points[i])
            {
                isAllReady = false;
                break;
            }
        }
        if (isAllReady)
        {
            for (int i = 0; i < points.Length; i++)
            {
                Vector2 uv = points[i].anchoredPosition;
                AddVertex(vh, uv);
            }
            AddTriangle(vh, points.Length);
        }
    }

    /// <summary>
    /// 添加顶点数据
    /// </summary>
    private void AddVertex(VertexHelper vh, Vector2 uv)
    {
        UIVertex vertex = UIVertex.simpleVert;
        vertex.color = color;
        Vector2 size = new Vector2(rectTransform.rect.width, rectTransform.rect.height);
        Vector2 pivot = rectTransform.pivot;
        vertex.position.x = uv.x + size.x * (0.5f - pivot.x);
        vertex.position.y = uv.y + size.y * (0.5f - pivot.y);
        Vector2 uv0 = new Vector2((uv.x + size.x * 0.5f) / size.x, (uv.y + size.y * 0.5f) / size.y);

        //支持贴图缩放
        uv0 *= texScale;
        uv0 -= Vector2.one * (texScale - 1f) * 0.5f;

        vertex.uv0 = uv0;
        vh.AddVert(vertex);
    }

    void AddTriangle(VertexHelper vh, int count)
    {
        for (int i = 1; i <= count; i++)
        {
            if (i < count)
            {
                vh.AddTriangle(0, i, i + 1);
            }
            else
            {
                vh.AddTriangle(0, i, 1);
            }
        }
    }

    void RefreshSizeDelta()
    {
        float maxX = 0;
        float maxY = 0;
        for (int i = 0; i < points.Length; i++)
        {
            RectTransform point = points[i];
            if (point)
            {
                if (Mathf.Abs(point.anchoredPosition.x) > maxX)
                {
                    maxX = Mathf.Abs(point.anchoredPosition.x);
                }
                if (Mathf.Abs(point.anchoredPosition.y) > maxY)
                {
                    maxY = Mathf.Abs(point.anchoredPosition.y);
                }
            }
        }
        rectTransform.sizeDelta = new Vector2(maxX * 2, maxY * 2);
    }

    //重写点击判断
    public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
    {
        //用所有连线判断相交次数的奇偶来判断是否点击在图形内
        Vector2 clickPos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out clickPos);
        return IsInPolygon(clickPos, poses);
    }

    bool IsInPolygon(Vector2 point, Vector2[] polygonPoints)
    {
        bool inside = false;
        int pointCount = polygonPoints.Length;
        Vector2 p1, p2;
        for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)
        {
            p1 = polygonPoints[i];
            p2 = polygonPoints[j];
            if (point.y < p2.y)
            {
                if (p1.y <= point.y)
                {
                    if ((point.y - p1.y) * (p2.x - p1.x) > (point.x - p1.x) * (p2.y - p1.y))
                    {
                        inside = (!inside);
                    }
                }
            }
            else if (point.y < p1.y)
            {
                if ((point.y - p1.y) * (p2.x - p1.x) < (point.x - p1.x) * (p2.y - p1.y))
                {
                    inside = (!inside);
                }
            }
        }
        return inside;
    }

#if UNITY_EDITOR
    [UnityEditor.MenuItem("BToolkit/创建 ImagePolygon")]
    [UnityEditor.MenuItem("GameObject/BToolkit/创建 ImagePolygon")]
    static void Create()
    {
        GameObject go = new GameObject("ImagePolygon");
        go.layer = LayerMask.NameToLayer("UI");
        go.transform.SetParent(UnityEditor.Selection.activeGameObject.transform, false);
        ImagePolygon image = go.AddComponent<ImagePolygon>();
        image.points = new RectTransform[3];
        for (int i = 0; i < image.points.Length; i++)
        {
            GameObject bar = new GameObject("Bar" + i);
            bar.layer = LayerMask.NameToLayer("UI");
            bar.transform.SetParent(go.transform, false);
            RectTransform rectTransform = bar.AddComponent<RectTransform>();
            rectTransform.sizeDelta = Vector2.zero;
            image.points[i] = rectTransform;
        }
        image.points[0].anchoredPosition = new Vector2(0, 50);
        image.points[1].anchoredPosition = new Vector2(50, -50);
        image.points[2].anchoredPosition = new Vector2(-50, -50);

        UnityEditor.EditorUtility.SetDirty(go);
    }
#endif
}